package my1024.view;

import java.util.Enumeration;

import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Group;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Vector3f;

import my1024.app.Const;
import my1024.model.BoxModel;
import my1024.utils.EventData;
import my1024.utils.EventType;

import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class MainSceneGraph {
	private BranchGroup mainBranch;
	private BranchGroup contentBranch;
	private TransformGroup root;

	public MainSceneGraph(SimpleUniverse universe) {
		initScene();
		centralize();
		addGrid();
		addMouseRotate();
	}

	public BranchGroup getBranchGroup() {
		contentBranch.compile();
		mainBranch.compile();
		return mainBranch;
	}

	private void initScene() {
		mainBranch = new BranchGroup();

		root = new TransformGroup();
		root.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		root.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		mainBranch.addChild(root);

		contentBranch = new BranchGroup();
		contentBranch.setCapability(Group.ALLOW_CHILDREN_EXTEND);
		contentBranch.setCapability(Group.ALLOW_CHILDREN_WRITE);
		contentBranch.setCapability(Group.ALLOW_CHILDREN_READ);
		root.addChild(contentBranch);
	}

	private void addMouseRotate() {
		MouseRotate mouseRotate = new MouseRotate();
		mouseRotate.setTransformGroup(root);
		mouseRotate.setSchedulingBounds(new BoundingSphere());
		root.addChild(mouseRotate);
	}

	private void centralize() {
		Vector3f vTrans = new Vector3f(Const.BOX_BOUND / 2, Const.BOX_BOUND / 2, 0);
		Transform3D translation = new Transform3D();
		translation.setTranslation(vTrans);
		root.setTransform(translation);
	}

	private void addGrid() {
		GridLine grid = new GridLine();
		grid.createGridLine();
		root.addChild(grid.getGridLine());
	}

	public void addObj(EventData obj) {
		System.out.println("ADD OBJ: " + obj.toString());
		BoxModel model = obj.getOldBox();
		contentBranch.addChild(new MyBox(model).getScene());
	}

	public void deleteObj(EventData obj) {
		BoxModel boxToDel = obj.getOldBox();
		System.out.println("DELETED OBJ: " + boxToDel.toString());

		int index = findBoxIndexInScene(boxToDel);
		if (index < contentBranch.numChildren()) {
			contentBranch.removeChild(index);
			// System.out.println("Remove child at " + index);
		} else {
			// System.out.println("Can not remove:" + boxToDel.toString());
		}
	}

	private int findBoxIndexInScene(BoxModel boxModel) {
		MyBox currentBox = null;
		int index = 0;

		Enumeration<?> allChildren = contentBranch.getAllChildren();
		while (allChildren.hasMoreElements()) {
			Object oneBranch = allChildren.nextElement();
			if (oneBranch instanceof BranchGroup) {
				currentBox = (MyBox) ((BranchGroup) oneBranch).getUserData();
				if (!currentBox.isMatchBoxModelId(boxModel)) {
					index++;
				} else {
					break;
				}
			}
		}
		return index;
	}

	public void changeObj(EventData obj) {
		BoxModel oldModel = obj.getOldBox();
		BoxModel newModel = obj.getNewBox();
		MyBox currentBox = null;

		Enumeration<?> allChildren = contentBranch.getAllChildren();
		while (allChildren.hasMoreElements()) {
			Object oneBranch = allChildren.nextElement();
			if (oneBranch instanceof BranchGroup) {
				currentBox = (MyBox) ((BranchGroup) oneBranch).getUserData();
				if (currentBox.isMatchBoxModelId(oldModel)) {
					if (EventType.MOVE_BOX == obj.getEventType()) {
						currentBox.moveBox(newModel);
					} else if (EventType.CHANGE_BOX == obj.getEventType()) {
						currentBox.changeBoxTexture(newModel);
					}
				}
			}
		}
	}

	public void resetRotate() {
		Transform3D noRotate = new Transform3D();
		noRotate.rotX(0);
		noRotate.rotY(0);
		root.setTransform(noRotate);
	}

	public void dump() {
		System.out.println("\nSceneGrapha:");
		Enumeration<?> allChildren = contentBranch.getAllChildren();
		while (allChildren.hasMoreElements()) {
			Object oneBranch = allChildren.nextElement();
			if (oneBranch instanceof BranchGroup) {
				MyBox box = (MyBox) ((BranchGroup) oneBranch).getUserData();
				System.out.println("BOX: " + box.getModel().toString());
			}
		}
	}
}
